home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume4 / rolodex / part2 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  59.4 KB

  1. From: ihnp4!think!massar (JP Massar)
  2. Subject: rolodex database program -- part 2 of 3
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 28
  7. Submitted by: ihnp4!think!massar (JP Massar)
  8.  
  9. #! /bin/sh
  10. # This is a shell archive, meaning:
  11. # 1. Remove everything above the #! /bin/sh line.
  12. # 2. Save the resulting text in a file.
  13. # 3. Execute the file with /bin/sh (not csh) to create the files:
  14. #    choices.h
  15. #    clear.c
  16. #    datadef.h
  17. #    io.c
  18. #    menuaux.c
  19. #    operations.c
  20. #    options.c
  21. #    rlist.c
  22. #    rolo.c
  23. #    rolodefs.h
  24. #    rolofiles.h
  25. #    search.c
  26. #    update.c
  27. # This archive created: Thu Mar 13 18:29:52 1986
  28. export PATH; PATH=/bin:$PATH
  29. echo shar: extracting "'choices.h'" '(685 characters)'
  30. if test -f 'choices.h'
  31. then
  32.     echo shar: will not over-write existing file "'choices.h'"
  33. else
  34. cat << \SHAR_EOF > 'choices.h'
  35. typedef enum { P_CONTINUE, P_NEXT_PERSON, P_ABORT, P_HELP } P_Choices;
  36.  
  37. typedef enum { 
  38.         
  39.         M_SEARCH_BY_OTHER, M_SEARCH_BY_NAME, M_PRINT_TO_LASER_PRINTER,
  40.         M_HELP, M_EXIT, M_PERUSE, M_SAVE, M_ADD
  41.  
  42.       } Main_Choices;
  43.  
  44. typedef enum { 
  45.  
  46.         A_ABORT_ADD, A_BACKUP, A_FILL_IN_REST,
  47.         A_ABORT_ROLO, A_HELP, A_NO_DATA
  48.  
  49.       } Add_Choices;
  50.  
  51. typedef enum { 
  52.         
  53.         E_ABORT, E_UPDATE, E_DELETE, E_CONTINUE, E_PREV, E_HELP, E_SCAN
  54.         
  55.       } E_Choices;
  56.  
  57. typedef enum { U_ABORT, U_HELP, U_END_UPDATE } U_Choices;
  58.  
  59. typedef enum { S_ABORT, S_HELP, S_SCAN_ONE_BY_ONE } S_Choices;
  60.  
  61. typedef enum { O_ABORT, O_HELP, O_BACKUP, O_DONE_OTHERS } O_Choices;
  62. SHAR_EOF
  63. if test 685 -ne "`wc -c < 'choices.h'`"
  64. then
  65.     echo shar: error transmitting "'choices.h'" '(should have been 685 characters)'
  66. fi
  67. fi
  68. echo shar: extracting "'clear.c'" '(930 characters)'
  69. if test -f 'clear.c'
  70. then
  71.     echo shar: will not over-write existing file "'clear.c'"
  72. else
  73. cat << \SHAR_EOF > 'clear.c'
  74. #include <stdio.h>
  75. #ifdef TERMINFO
  76. #include <term.h>
  77. #endif
  78. #undef putchar
  79.  
  80. int putchar();
  81. static int ok_to_clear;
  82.  
  83. #ifdef TERMCAP
  84. static char clear_screen[128] = 0;
  85. static int lines;
  86. #endif
  87.  
  88. clearinit ()
  89. {
  90. #ifdef TERMINFO
  91.   int i;        
  92.   setupterm(getenv("TERM"),1,&i);
  93.   ok_to_clear = (i == 1) ? 1 : 0;
  94.   if (i != 1) {
  95.      fprintf(stderr,"Warning: Terminal type unknown\n");
  96.   }
  97.   return (i == 1) ? 0 : -1;
  98. #endif
  99. #ifdef TERMCAP
  100.   char tc[1024];
  101.   char *ptr = clear_screen;
  102.  
  103.   if (tgetent(tc, getenv("TERM")) < 1) {
  104.     ok_to_clear = 0;
  105.     return;
  106.   }
  107.   tgetstr("cl", &ptr);
  108.   lines = tgetnum("li");
  109.   ok_to_clear = (clear_screen[0] != 0 && lines > 0);
  110.  
  111. #endif
  112. }        
  113.         
  114. clear_the_screen ()
  115. {
  116. #ifdef TERMINFO
  117.   if (!ok_to_clear) return;        
  118.   tputs(clear_screen,lines,putchar);
  119.   fflush(stdout);
  120. #endif
  121. #ifdef TERMCAP
  122.   if (!ok_to_clear) return;
  123.   tputs(clear_screen,lines,putchar);
  124.   fflush(stdout);
  125. #endif
  126. }
  127. SHAR_EOF
  128. if test 930 -ne "`wc -c < 'clear.c'`"
  129. then
  130.     echo shar: error transmitting "'clear.c'" '(should have been 930 characters)'
  131. fi
  132. fi
  133. echo shar: extracting "'datadef.h'" '(1911 characters)'
  134. if test -f 'datadef.h'
  135. then
  136.     echo shar: will not over-write existing file "'datadef.h'"
  137. else
  138. cat << \SHAR_EOF > 'datadef.h'
  139. #define ABORTSTRING "\\"
  140. #define ABORTCHAR '\\'
  141.  
  142. #define MAXMATCHES 17
  143.  
  144. #define N_BASIC_FIELDS 8
  145. #define OTHER -1
  146.  
  147. typedef enum Basic_Field {
  148.  
  149.     R_NAME = 0, R_WORK_PHONE, R_HOME_PHONE, R_COMPANY, R_WORK_ADDRESS,
  150.     R_HOME_ADDRESS, R_REMARKS, R_UPDATED
  151.  
  152.   };    
  153.     
  154. extern char *Field_Names[];  
  155.   
  156. /* A Rolodex entry */
  157.  
  158. typedef struct {
  159.  
  160.     char *basicfields[N_BASIC_FIELDS];
  161.     int n_others;
  162.     char **other_fields;
  163.  
  164.   } Rolo_Entry, *Ptr_Rolo_Entry;
  165.  
  166.   
  167. #define get_basic_rolo_field(n,x) (((x) -> basicfields)[(n)])
  168. #define get_n_others(x) ((x) -> n_others)  
  169. #define get_other_field(n,x) (((x) -> other_fields)[n])
  170.   
  171. #define set_basic_rolo_field(n,x,s) (((x) -> basicfields[(n)]) = (s))
  172. #define set_n_others(x,n) (((x) -> n_others) = (n))
  173. #define incr_n_others(x) (((x) -> n_others)++)
  174. #define set_other_field(n,x,s) ((((x) -> other_fields)[n]) = (s))
  175.  
  176. typedef struct link {
  177.  
  178.     Ptr_Rolo_Entry entry;
  179.     int matched;
  180.     struct link *prev;
  181.     struct link *next;
  182.  
  183.   } Rolo_List, *Ptr_Rolo_List;
  184.  
  185.  
  186. #define get_next_link(x) ((x) -> next)
  187. #define get_prev_link(x) ((x) -> prev)
  188. #define get_entry(x)     ((x) -> entry)
  189. #define get_matched(x) ((x) -> matched)
  190.  
  191. #define set_next_link(x,y) (((x) -> next) = (y))
  192. #define set_prev_link(x,y) (((x) -> prev) = (y))
  193. #define set_entry(x,y) (((x) -> entry) = (y))
  194. #define set_matched(x) (((x) -> matched) = 1)
  195. #define unset_matched(x) (((x) -> matched) = 0);
  196.  
  197. extern Ptr_Rolo_List Begin_Rlist;
  198. extern Ptr_Rolo_List End_Rlist;
  199.  
  200. #define MAXLINELEN 80
  201. #define DIRPATHLEN 100
  202.  
  203. extern int changed;
  204. extern int reorder_file;
  205. extern int rololocked;
  206.  
  207. extern char *rolo_emalloc();
  208. extern char *malloc();
  209. extern Ptr_Rolo_List new_link_with_entry();
  210. extern char *copystr();
  211. extern int compare_links();
  212. extern char *timestring();
  213. extern char *homedir(), *libdir();
  214. extern char *getenv();
  215. extern char *ctime();
  216. extern char *select_search_string();
  217. extern int in_search_mode;
  218. SHAR_EOF
  219. if test 1911 -ne "`wc -c < 'datadef.h'`"
  220. then
  221.     echo shar: error transmitting "'datadef.h'" '(should have been 1911 characters)'
  222. fi
  223. fi
  224. echo shar: extracting "'io.c'" '(8455 characters)'
  225. if test -f 'io.c'
  226. then
  227.     echo shar: will not over-write existing file "'io.c'"
  228. else
  229. cat << \SHAR_EOF > 'io.c'
  230. #include <stdio.h>
  231. #include <sys/types.h>
  232. #include <sys/stat.h>
  233. #include <sys/file.h>
  234. #include <ctype.h>
  235.  
  236. #include "sys5.h"
  237.  
  238. #ifdef TMC
  239. #include <ctools.h>
  240. #else
  241. #include "ctools.h"
  242. #endif
  243.  
  244. #include "datadef.h"
  245. #include "rolofiles.h"
  246.  
  247.  
  248. char *Field_Names[N_BASIC_FIELDS] = {
  249.         
  250.         "Name: ", "Work Phone: ", "Home Phone: ", "Company: ",
  251.         "Work Address: ", "Home Address: ", "Remarks: ", "Date Updated: "
  252.         
  253.      };
  254.  
  255. Ptr_Rolo_List Begin_Rlist = 0;
  256. Ptr_Rolo_List End_Rlist = 0;
  257. Ptr_Rolo_List Current_Entry = 0;
  258.  
  259. static char *rolofiledata;
  260.  
  261. read_rolodex (fd) int fd;
  262.  
  263. {
  264.   struct stat statdata;
  265.   int filesize,i,j,k,start_of_others,warning_given;
  266.   Ptr_Rolo_Entry newentry,oldentry,currententry;
  267.   Ptr_Rolo_List newlink,rptr;
  268.   char *next_field,*next_other,*oldname,*currentname;
  269.   char **other_pointers;
  270.   int n_entries = 0;
  271.   
  272.   /* find out how many bytes are in the file */
  273.   
  274.   fstat(fd,&statdata);
  275.   if ((filesize = statdata.st_size) == 0) {
  276.      return(0);
  277.   }
  278.  
  279.   /* create an array of characters that big */
  280.   
  281.   rolofiledata = rolo_emalloc(filesize);
  282.  
  283.   /* read them all in at once for efficiency */
  284.   
  285.   if (filesize != read(fd,rolofiledata,filesize)) {
  286.      fprintf(stderr,"rolodex read failed\n");
  287.      exit(-1);
  288.   }
  289.  
  290.   j = 0;
  291.   
  292.   /* for each entry in the rolodex file */
  293.   
  294.   while (j < filesize) {
  295.  
  296.       n_entries++;
  297.         
  298.       /* create the link and space for the data entry */
  299.         
  300.       newlink = new_link_with_entry();
  301.       newentry = get_entry(newlink);
  302.       if (j == 0) {
  303.          Begin_Rlist = newlink;
  304.          set_prev_link(newlink,0);
  305.          set_next_link(newlink,0);
  306.       }
  307.       else {
  308.           set_next_link(End_Rlist,newlink);
  309.           set_prev_link(newlink,End_Rlist);
  310.           set_next_link(newlink,0);
  311.       }
  312.       End_Rlist = newlink;
  313.  
  314.       /* locate each required field in the character array and change */
  315.       /* the ending line feed to a null.  Insert a pointer to the */
  316.       /* beginning of the field into the data entry */
  317.  
  318.       for (i = 0; i < N_BASIC_FIELDS; i++) {
  319.           next_field = rolofiledata + j;
  320.           while (rolofiledata[j] != '\n') {
  321.             j++;
  322.           }
  323.           rolofiledata[j] = '\0';
  324.           j++;
  325.           set_basic_rolo_field(i,newentry,next_field);
  326.       }
  327.  
  328.       /* the end of an entry is indicated by two adjacent newlines */
  329.  
  330.       if (rolofiledata[j] == '\n') {
  331.          j++;
  332.          newentry -> other_fields = 0;
  333.          continue;
  334.       }
  335.  
  336.       /* there must be additional, user-inserted fields. Find out how many. */
  337.  
  338.       start_of_others = j;
  339.       while (1) {
  340.         while (rolofiledata[j] != '\n') {
  341.           j++;
  342.         }
  343.         incr_n_others(newentry);
  344.         j++;
  345.         if (rolofiledata[j] == '\n') {
  346.            j++;
  347.            break;
  348.         }
  349.      }
  350.  
  351.      /* allocate an array of character pointers to hold these fields */
  352.  
  353.      other_pointers = (char **)rolo_emalloc(get_n_others(newentry)*sizeof(char *));
  354.  
  355.      /* separate each field and insert a pointer to it in the char array */
  356.  
  357.      k = start_of_others;
  358.      for (i = 0; i < get_n_others(newentry); i++) {
  359.          next_other = rolofiledata + k;
  360.          while (rolofiledata[k] != '\n') {
  361.            k++;
  362.          }
  363.          rolofiledata[k] = '\0';
  364.          other_pointers[i] = next_other;
  365.          k++;
  366.      }
  367.  
  368.      /* insert the pointer to this character array into the data entry */
  369.  
  370.      newentry -> other_fields = other_pointers;
  371.  
  372.   }
  373.  
  374.   /* check that all the entries are in alphabetical order by name */
  375.   
  376.   warning_given = 0;
  377.   rptr = get_next_link(Begin_Rlist);
  378.   while (rptr != 0) {
  379.     if (1 == compare_links(get_prev_link(rptr),rptr)) {
  380.        if (!warning_given) fprintf(stderr,"Warning, rolodex out of order\n");
  381.        warning_given = 1;
  382.        reorder_file = 1;
  383.     }
  384.     rptr = get_next_link(rptr);
  385.   }    
  386.     
  387.   return(n_entries);
  388.   
  389. }
  390.  
  391.  
  392. write_rolo_list (fp) FILE *fp; 
  393.  
  394. /* write the entire in-core rolodex to a file */
  395.  
  396. {
  397.  
  398.   Ptr_Rolo_List rptr;
  399.   Ptr_Rolo_Entry entry;
  400.   int j;
  401.  
  402.   rptr = Begin_Rlist;
  403.  
  404.   while (rptr != 0) {
  405.     entry = get_entry(rptr);
  406.     for (j = 0; j < N_BASIC_FIELDS; j++) {
  407.         fprintf(fp,"%s\n",get_basic_rolo_field(j,entry));
  408.     }
  409.     for (j = 0; j < get_n_others(entry); j++) {
  410.         fprintf(fp,"%s\n",get_other_field(j,entry));
  411.     }
  412.     fprintf(fp,"\n");
  413.     rptr = get_next_link(rptr);
  414.   }
  415.  
  416. }
  417.  
  418.  
  419. write_rolo (fp1,fp2) FILE *fp1; FILE *fp2;
  420.  
  421. {
  422.   write_rolo_list(fp1);
  423.   write_rolo_list(fp2);
  424. }
  425.  
  426.  
  427. display_basic_field (name,value,show,up) char *name; char *value; int show,up;
  428. {
  429.   int semi = 0;        
  430.   int i;
  431.   if (all_whitespace(value) && !show) return;
  432.   printf("%-25s",name);
  433.   while (*value != '\0') {
  434.     if (*value == ';') {
  435.        while (*++value == ' '); 
  436.        putchar('\n');
  437.        for (i = 0; i < (up ? 28 : 25); i++) putchar(' ');
  438.        semi = 1;
  439.     }
  440.     else {
  441.        semi = 0;
  442.        putchar(*value++);
  443.     }
  444.   }
  445.   putchar('\n');
  446. }
  447.  
  448.  
  449. display_other_field (fieldstring) char *fieldstring;
  450. {
  451.   int already_put_sep = 0;        
  452.   int count = 0;
  453.   int i;
  454.   while (*fieldstring != '\0') {
  455.     if (*fieldstring == ';' && already_put_sep) {
  456.        while (*++fieldstring == ' ');
  457.        putchar('\n');
  458.        for (i = 0; i < 25; i++) putchar(' ');
  459.        continue;
  460.     }
  461.     putchar(*fieldstring);
  462.     count++;
  463.     if (*fieldstring == ':' && !already_put_sep) {
  464.        for (i = count; i < 24; i++) putchar(' ');
  465.        already_put_sep = 1;
  466.     }
  467.     fieldstring++;
  468.   }
  469.   putchar('\n');
  470. }
  471.  
  472.  
  473. summarize_entry_list (rlist,ss) Ptr_Rolo_List rlist; char *ss;
  474.  
  475. /* print out the Name field for each entry that is tagged as matched */
  476. /* and number each entry. */
  477.  
  478. {
  479.   int count = 1;
  480.   clear_the_screen();
  481.   printf("Entries that match '%s' :\n\n",ss);
  482.   while (rlist != 0) {
  483.     if (get_matched(rlist)) {
  484.        printf (
  485.           "%d. \t%s\n",
  486.           count++,
  487.           get_basic_rolo_field((int) R_NAME,get_entry(rlist))
  488.        );
  489.     }
  490.     rlist = get_next_link(rlist);    
  491.   }
  492.   putchar('\n');
  493. }
  494.  
  495.  
  496. display_field_names ()
  497.  
  498. /* display and number each standard field name. */
  499.  
  500. {
  501.   int j;
  502.   char *name;
  503.   clear_the_screen();
  504.   for (j = 0; j < N_BASIC_FIELDS - 1; j++) {        
  505.       name = Field_Names[j];        
  506.       printf("%d. ",j+1);
  507.       while (*name != ':') putchar(*name++);
  508.       putchar('\n');
  509.   }
  510.   printf("%d. ",N_BASIC_FIELDS);
  511.   printf("A user created item name\n\n");
  512. }  
  513.   
  514.  
  515. display_entry (entry) Ptr_Rolo_Entry entry;
  516.  
  517. {
  518.   int j,n_others;
  519.   char *string;
  520.   
  521.   clear_the_screen();
  522.   
  523.   /* display the standard fields other than Date Updated */
  524.   
  525.   for (j = 0; j < N_BASIC_FIELDS - 1; j++) {
  526.       string = get_basic_rolo_field(j,entry);
  527.       display_basic_field(Field_Names[j],string,0,0);
  528.   }        
  529.       
  530.   /* display any additional fields the user has defined for this entry */
  531.   
  532.   n_others = get_n_others(entry);
  533.   for (j = 0; j < n_others; j++) {
  534.       string = get_other_field(j,entry);
  535.       display_other_field(string);
  536.    }
  537.  
  538.    /* display the Date Updated field */
  539.    
  540.    j = N_BASIC_FIELDS - 1;
  541.    display_basic_field(Field_Names[j],get_basic_rolo_field(j,entry),0,0);
  542.    fprintf(stdout,"\n");
  543.  
  544. }
  545.  
  546.  
  547. display_entry_for_update (entry) Ptr_Rolo_Entry entry;
  548.  
  549. /* same as display_entry, except each item is numbered and the Date Updated */
  550. /* item is not displayed */
  551.  
  552. {
  553.   int j,n_others;
  554.   char *string;
  555.   int count = 1;
  556.   
  557.   clear_the_screen();
  558.   
  559.   for (j = 0; j < N_BASIC_FIELDS - 1; j++) {
  560.       string = get_basic_rolo_field(j,entry);
  561.       printf("%d. ",count++);
  562.       display_basic_field(Field_Names[j],string,1,1);
  563.   }        
  564.       
  565.   n_others = get_n_others(entry);
  566.   for (j = 0; j < n_others; j++) {
  567.       string = get_other_field(j,entry);
  568.       printf("%d. ",count++);
  569.       display_other_field(string);
  570.   }
  571.   
  572.   printf("%d. Add a new user defined field\n",count);
  573.  
  574.   fprintf(stdout,"\n");
  575.  
  576. }
  577.  
  578.  
  579. int cathelpfile (filepath,helptopic,clear) 
  580.  
  581.   char *filepath, *helptopic; 
  582.   int clear;
  583.  
  584. {
  585.   FILE *fp;          
  586.   char buffer[MAXLINELEN];
  587.   if (clear) clear_the_screen();
  588.   if (NULL == (fp = fopen(filepath,"r"))) {
  589.      if (helptopic) {
  590.         printf("No help available on %s, sorry.\n\n",helptopic); 
  591.      }
  592.      else {
  593.         fprintf(stderr,"Fatal error, can't open %s\n",filepath);
  594.         exit(-1);
  595.      }
  596.      return;
  597.   }
  598.   while (NULL != fgets(buffer,MAXLINELEN,fp)) printf("%s",buffer);  
  599.   printf("\n");
  600.   fclose(fp);
  601.   return;
  602. }
  603.  
  604.  
  605. any_char_to_continue ()
  606. {
  607.   char buffer[80];
  608.   printf("RETURN to continue: ");
  609.   fgets(buffer,80,stdin);
  610.   return;
  611. }
  612. SHAR_EOF
  613. if test 8455 -ne "`wc -c < 'io.c'`"
  614. then
  615.     echo shar: error transmitting "'io.c'" '(should have been 8455 characters)'
  616. fi
  617. fi
  618. echo shar: extracting "'menuaux.c'" '(1433 characters)'
  619. if test -f 'menuaux.c'
  620. then
  621.     echo shar: will not over-write existing file "'menuaux.c'"
  622. else
  623. cat << \SHAR_EOF > 'menuaux.c'
  624. #include <stdio.h>
  625. #include <ctype.h>
  626.  
  627. #include "sys5.h"
  628.  
  629. #ifdef TMC
  630. #include <ctools.h>
  631. #else
  632. #include "ctools.h"
  633. #endif
  634. #include "args.h"
  635. #include "menu.h"
  636.  
  637. #include "rolofiles.h"
  638. #include "rolodefs.h"
  639. #include "datadef.h"
  640.  
  641.  
  642. rolo_menu_yes_no (prompt,rtn_default,help_allowed,helpfile,subject)
  643.  
  644.   char *prompt;
  645.   int rtn_default;
  646.   int help_allowed;
  647.   char *helpfile, *subject;
  648.   
  649. {
  650.   int rval;
  651.   reask :
  652.   rval = menu_yes_no_abort_or_help (
  653.               prompt,ABORTSTRING,help_allowed,rtn_default
  654.            );
  655.   switch (rval) {
  656.     case MENU_EOF :
  657.       user_eof();
  658.       break;
  659.     case MENU_HELP : 
  660.       cathelpfile(libdir(helpfile),subject,1);
  661.       goto reask;
  662.       break;
  663.     default :
  664.       return(rval);
  665.       break;
  666.   }
  667. }
  668.   
  669.  
  670. rolo_menu_data_help_or_abort (prompt,helpfile,subject,ptr_response)
  671.  
  672.   char *prompt, *helpfile, *subject;
  673.   char **ptr_response;
  674.   
  675.   int rval;
  676.   reask :
  677.   rval = menu_data_help_or_abort(prompt,ABORTSTRING,ptr_response);
  678.   if (rval == MENU_EOF) user_eof();
  679.   if (rval == MENU_HELP) {
  680.      cathelpfile(libdir(helpfile),subject,1);
  681.      goto reask;
  682.   }     
  683.   return(rval);
  684. }
  685.      
  686.  
  687. rolo_menu_number_help_or_abort (prompt,low,high,ptr_ival)
  688.  
  689.   char *prompt;
  690.   int low,high,*ptr_ival;
  691.   
  692. {  
  693.   int rval;
  694.   if (MENU_EOF == (rval = menu_number_help_or_abort (
  695.                                prompt,ABORTSTRING,low,high,ptr_ival
  696.                            )))
  697.      user_eof();
  698.   return(rval);
  699. }
  700. SHAR_EOF
  701. if test 1433 -ne "`wc -c < 'menuaux.c'`"
  702. then
  703.     echo shar: error transmitting "'menuaux.c'" '(should have been 1433 characters)'
  704. fi
  705. fi
  706. echo shar: extracting "'operations.c'" '(8950 characters)'
  707. if test -f 'operations.c'
  708. then
  709.     echo shar: will not over-write existing file "'operations.c'"
  710. else
  711. cat << \SHAR_EOF > 'operations.c'
  712. #include <stdio.h>
  713. #include <ctype.h>
  714.  
  715. #include "sys5.h"
  716.  
  717. #ifdef TMC
  718. #include <ctools.h>
  719. #else
  720. #include "ctools.h"
  721. #endif
  722. #include "args.h"
  723. #include "menu.h"
  724. #include "mem.h"
  725.  
  726.  
  727. #include "rolofiles.h"
  728. #include "rolodefs.h"
  729. #include "datadef.h"
  730. #include "choices.h"
  731.  
  732. extern char *ctime();
  733.  
  734. Ptr_Rolo_List create_entry (basicdata,otherdata) char **basicdata, **otherdata;
  735. {
  736.   Ptr_Rolo_List newlink;        
  737.   Ptr_Rolo_Entry newentry;
  738.   int i,j;
  739.   newlink = new_link_with_entry();        
  740.   newentry = get_entry(newlink);
  741.   for (j = 0; j < N_BASIC_FIELDS; j++) {
  742.       set_basic_rolo_field(j,newentry,basicdata[j]);
  743.   }
  744.   j = 0;
  745.   while (otherdata[j] != 0) j++;
  746.   set_n_others(newentry,j);
  747.   if (j > 0) {
  748.      newentry -> other_fields = (char **) rolo_emalloc(j*sizeof(char *));
  749.      for (i = 0; i < j; i++) {
  750.          set_other_field(i,newentry,otherdata[i]);
  751.      }
  752.   }
  753.   else newentry -> other_fields = 0;
  754.   return(newlink);
  755. }  
  756.   
  757.  
  758. other_fields () 
  759. {
  760.   int rval;        
  761.   rval = rolo_menu_yes_no (
  762.              "Additional fields? ",DEFAULT_NO,1,
  763.              "morefieldshelp","additional fields"
  764.           );
  765.   return(rval == MENU_YES);
  766. }
  767.  
  768.  
  769. add_the_entry ()
  770. {
  771.   return(MENU_YES == rolo_menu_yes_no (
  772.               "Add new entry to rolodex? ",DEFAULT_YES,1,
  773.               "newaddhelp","adding newly entered entry"
  774.            ));
  775. }
  776.  
  777.  
  778. rolo_add () 
  779.  
  780. {
  781.   int i,j,k,rval,menuval;
  782.   long timeval;
  783.   char *response;
  784.   char *basicdata[N_BASIC_FIELDS], *otherdata[100], *datum;
  785.   Ptr_Rolo_List rlink;
  786.         
  787.   for (j = 0; j < 100; j++) otherdata[j] = 0;
  788.   for (j = 0; j < N_BASIC_FIELDS; j++) basicdata[j] = 0;
  789.   cathelpfile(libdir("addinfo"),0,1);
  790.   
  791.   /* 'k' and 'kludge' are are kludge to allow us to back up from entering */
  792.   /* user defined fields to go an correct wrong basic field information. */
  793.   
  794.   k = 0;
  795.   
  796.   kludge :
  797.   
  798.   for (j = k; j < N_BASIC_FIELDS - 1; j++) {
  799.         
  800.       redo :
  801.         
  802.       rval = menu_match (
  803.            &menuval,&response,
  804.            Field_Names[j],
  805.            0,0,0,1,5,
  806.            "\\",A_ABORT_ADD,
  807.            "^",A_BACKUP,
  808.            "!",A_FILL_IN_REST,
  809.            "?",A_HELP,
  810.            "",A_NO_DATA
  811.         );
  812.         
  813.       switch (rval) {
  814.         
  815.         case MENU_NO_MATCH :
  816.           basicdata[j] = copystr(response);
  817.           if (j == 0 && strlen(basicdata[j]) == 0) {
  818.              printf("Each entry must have a name!\n");
  819.              goto redo;
  820.           }
  821.           break;
  822.  
  823.         case MENU_MATCH :
  824.           switch (menuval) {
  825.             case A_BACKUP :
  826.               if (j == 0) return;
  827.               j--;
  828.               goto redo;
  829.               break;
  830.             case A_ABORT_ADD :
  831.               return;
  832.               break;
  833.             case A_FILL_IN_REST :
  834.               if (j == 0) {
  835.                  fprintf(stderr,"You must enter at least a name...\n");
  836.                  goto redo;
  837.               }
  838.               goto add_entry;
  839.               break;
  840.             case A_HELP :
  841.               cathelpfile(libdir("addhelp"),"adding entries",1);
  842.               any_char_to_continue();
  843.               clear_the_screen();
  844.               cathelpfile(libdir("addinfo"),0,0);
  845.               for (i = 0; i < j; i++) {
  846.                   printf("%s%s\n",Field_Names[i],basicdata[i]);
  847.               }
  848.               goto redo;
  849.               break;
  850.             case A_NO_DATA :
  851.               if (basicdata[j] != 0) basicdata[j][0] = '\0';
  852.               break;
  853.             default :
  854.               fprintf(stderr,"Impossible rval from rolo_add menu_match\n");
  855.               save_and_exit(-1);
  856.               break;
  857.           }
  858.           break;
  859.  
  860.         case MENU_EOF :
  861.           user_eof();
  862.           break;
  863.           
  864.         case MENU_ERROR :
  865.         case MENU_AMBIGUOUS :
  866.         default :
  867.           fprintf(stderr,"Impossible return from rolo_add menu_match\n");
  868.           save_and_exit(-1);
  869.           break;
  870.  
  871.       }
  872.  
  873.   }
  874.  
  875.   if (other_fields()) {
  876.      for (j = 0; j < 100; j++) {
  877.          redo_other :
  878.          rval = menu_match (
  879.               &menuval,&response,
  880.               "Enter <name>: <data> (type RETURN to quit) : ",
  881.               0,0,0,0,5,
  882.               "\\",O_ABORT,
  883.               "?",O_HELP,
  884.               "Help",O_HELP,
  885.               "^",O_BACKUP,
  886.               "",O_DONE_OTHERS
  887.            );
  888.          switch (rval) {
  889.            case MENU_MATCH :
  890.              switch (menuval) {
  891.                case O_DONE_OTHERS :
  892.                  goto add_entry;
  893.                  break;
  894.                case O_BACKUP :
  895.                  if (j == 0) {
  896.                     k = N_BASIC_FIELDS - 2;
  897.                     goto kludge;
  898.                  }
  899.                  else {
  900.                     j--;
  901.                     printf("Deleting %s\n",otherdata[j]);
  902.                     goto redo_other;
  903.                  }
  904.                  break;
  905.                case O_ABORT :
  906.                  return;
  907.                  break;
  908.                case O_HELP :
  909.                  cathelpfile(libdir("otherformathelp"),"user-item format",1);
  910.                  any_char_to_continue();
  911.                  goto redo_other;
  912.               }   
  913.              break;
  914.            case MENU_NO_MATCH :
  915.              if (0 == index(response,':')) {
  916.                 printf("No field name provided -- separate with a ':'.\n");
  917.                 goto redo_other;
  918.              }
  919.              otherdata[j] = copystr(response);
  920.              break;
  921.            case MENU_EOF :
  922.              user_eof();
  923.              break;
  924.            case MENU_AMBIGUOUS :
  925.            case MENU_ERROR :
  926.            default :
  927.              fprintf(stderr,"Impossible rval from add_other menu_match\n");
  928.              save_and_exit(-1);
  929.          }
  930.      }
  931.   }
  932.  
  933.   add_entry :   
  934.  
  935.   basicdata[N_BASIC_FIELDS - 1] = timestring();
  936.   
  937.   rlink = create_entry(basicdata,otherdata);
  938.   clear_the_screen();
  939.   display_entry(get_entry(rlink));
  940.   if (add_the_entry()) {
  941.      printf (
  942.          "Adding entry for %s to rolodex\n",
  943.          get_basic_rolo_field((int) R_NAME,get_entry(rlink))
  944.       );
  945.      rolo_insert(rlink,compare_links);
  946.      changed = 1;
  947.      sleep(2);
  948.   }
  949.   else {
  950.      return;
  951.   }
  952.  
  953. }
  954.  
  955.  
  956. entry_action (rlink) Ptr_Rolo_List rlink;
  957.  
  958. {
  959.   static entry_menu_displayed = 0;
  960.   int rval,menuval;
  961.   char *response;
  962.   
  963.   if (!entry_menu_displayed) cathelpfile(libdir("entrymenu"),0,0);
  964.   entry_menu_displayed = 1;
  965.   
  966.   redo :
  967.   
  968.   rval = menu_match (
  969.        &menuval, &response,
  970.        "Action (? for help) : ",
  971.        0,1,1,1,7,
  972.        "\\",E_ABORT,
  973.        "?",E_HELP,
  974.        "",E_CONTINUE,
  975.        "-",E_DELETE,
  976.        "+",E_UPDATE,
  977.        "<",E_PREV,
  978.        "%",E_SCAN
  979.     );
  980.     
  981.   if (rval != MENU_MATCH) {
  982.      if (rval == MENU_EOF) user_eof();
  983.      fprintf(stderr,"Impossible return from entry_action menu_match\n");
  984.      save_and_exit(-1);
  985.   }
  986.  
  987.   switch (menuval) {
  988.     case E_ABORT :
  989.     case E_CONTINUE :
  990.     case E_PREV :
  991.       break;
  992.     case E_SCAN :
  993.       rolo_peruse_mode(get_next_link(rlink));
  994.       break;
  995.     case E_UPDATE :
  996.       rolo_update_mode(rlink);
  997.       break;
  998.     case E_DELETE :
  999.       rolo_delete(rlink);
  1000.       printf("Entry deleted\n");
  1001.       sleep(1);
  1002.       changed = 1;
  1003.       break;
  1004.     case E_HELP :
  1005.       cathelpfile (
  1006.           libdir(in_search_mode ? "esearchhelp" : "escanhelp"),
  1007.           "entry actions",
  1008.           1
  1009.        );
  1010.       any_char_to_continue();
  1011.       clear_the_screen();
  1012.       display_entry(get_entry(rlink));
  1013.       goto redo;
  1014.       break;
  1015.     default :
  1016.       fprintf(stderr,"Impossible menuval in entry_action\n");
  1017.       save_and_exit(-1);
  1018.   }
  1019.  
  1020.   return(menuval);
  1021.   
  1022. }
  1023.  
  1024.  
  1025. display_list_of_entries (rlist) Ptr_Rolo_List rlist;
  1026.  
  1027. {
  1028.   Ptr_Rolo_List old;
  1029.         
  1030.   while (rlist != 0) {        
  1031.     
  1032.     if (!get_matched(rlist)) goto next;
  1033.         
  1034.     loop :    
  1035.     
  1036.     display_entry(get_entry(rlist));
  1037.     
  1038.     switch (entry_action(rlist)) {
  1039.       case E_CONTINUE :
  1040.         break;
  1041.       case E_ABORT :
  1042.         return;
  1043.         break;
  1044.       case E_PREV :
  1045.         old = rlist;
  1046.         find_prev_match :
  1047.         if (get_prev_link(rlist) == 0) {
  1048.            rlist = old;
  1049.            printf("No previous entry in scan list\n");
  1050.            sleep(2);
  1051.         }
  1052.         else {
  1053.            rlist = get_prev_link(rlist);
  1054.            if (!get_matched(rlist)) goto find_prev_match;
  1055.         }
  1056.         goto loop;
  1057.         break;
  1058.       default :
  1059.         printf("Displaying next entry in scan list...\n");
  1060.         sleep(1);
  1061.         break;
  1062.     }
  1063.     
  1064.     next :
  1065.     
  1066.     rlist = get_next_link(rlist);
  1067.     
  1068.   }
  1069.   
  1070.   printf("No further entries to scan...\n");
  1071.   sleep(2);     
  1072.   
  1073. }
  1074.   
  1075.  
  1076. rolo_peruse_mode (first_rlink) Ptr_Rolo_List first_rlink;
  1077.  
  1078. {
  1079.   int rval;
  1080.   Ptr_Rolo_List rlist = first_rlink;
  1081.   if (0 == Begin_Rlist) {
  1082.      fprintf(stderr,"No further entries in rolodex...\n");
  1083.      sleep(2);
  1084.      return;
  1085.   }
  1086.   while (rlist != 0) {  
  1087.     set_matched(rlist);
  1088.     rlist = get_next_link(rlist);
  1089.   }    
  1090.   display_list_of_entries(first_rlink);
  1091.   rlist = first_rlink;
  1092.   while (rlist != 0) {  
  1093.     unset_matched(rlist);
  1094.     rlist = get_next_link(rlist);
  1095.   }    
  1096. }
  1097. SHAR_EOF
  1098. if test 8950 -ne "`wc -c < 'operations.c'`"
  1099. then
  1100.     echo shar: error transmitting "'operations.c'" '(should have been 8950 characters)'
  1101. fi
  1102. fi
  1103. echo shar: extracting "'options.c'" '(6785 characters)'
  1104. if test -f 'options.c'
  1105. then
  1106.     echo shar: will not over-write existing file "'options.c'"
  1107. else
  1108. cat << \SHAR_EOF > 'options.c'
  1109. #include <sys/file.h>
  1110. #include <stdio.h>
  1111. #include <ctype.h>
  1112. #include <sgtty.h>
  1113. #include <sys/time.h>
  1114. #include <signal.h>
  1115.  
  1116. #include "sys5.h"
  1117.  
  1118. #ifdef TMC
  1119. #include <ctools.h>
  1120. #else
  1121. #include "ctools.h"
  1122. #endif
  1123. #include "args.h"
  1124. #include "menu.h"
  1125. #include "mem.h"
  1126.  
  1127. #include "rolofiles.h"
  1128. #include "rolodefs.h"
  1129. #include "datadef.h"
  1130. #include "choices.h"
  1131.  
  1132.  
  1133. print_short ()
  1134.  
  1135. /* print the names and phone numbers of everyone in the rolodex. */
  1136.  
  1137.  
  1138.   Ptr_Rolo_List rptr;
  1139.   Ptr_Rolo_Entry entry;
  1140.         
  1141.   rptr = Begin_Rlist;
  1142.   if (rptr == 0) {
  1143.      fprintf(stderr,"No entries to print out...\n");
  1144.      return;
  1145.   }
  1146.    
  1147.   fprintf (
  1148.      stdout,
  1149.      "\nNAME                      WORK PHONE                HOME PHONE"
  1150.    );
  1151.   fprintf (
  1152.      stdout,
  1153.      "\n----                      ----------                ----------\n\n\n"
  1154.    );
  1155.  
  1156.    while (rptr != 0) {
  1157.         entry = get_entry(rptr);
  1158.         fprintf (
  1159.             stdout,
  1160.             "%-25s %-25s %-25s\n",
  1161.             get_basic_rolo_field((int) R_NAME,entry),
  1162.             get_basic_rolo_field((int) R_WORK_PHONE,entry),
  1163.             get_basic_rolo_field((int) R_HOME_PHONE,entry)
  1164.          );   
  1165.          rptr = get_next_link(rptr);
  1166.    }       
  1167.    
  1168.  }  
  1169.    
  1170.  
  1171. person_match (person,entry) char *person; Ptr_Rolo_Entry entry; 
  1172.  
  1173. /* Match against a rolodex entry's Name and Company fields. */
  1174. /* Thus if I say 'rolo CCA' I will find people who work at CCA. */
  1175. /* This is good because sometimes you will forget a name but remember */
  1176. /* the company the person works for. */
  1177.  
  1178.   char *name, *company;        
  1179.   int len;
  1180.   len = strlen(person);
  1181.   name = get_basic_rolo_field((int) R_NAME,entry);
  1182.   company = get_basic_rolo_field((int) R_COMPANY,entry);
  1183.   if (strncsearch(name,strlen(name),person,len)) return(1);
  1184.   if (strncsearch(company,strlen(company),person,len)) return(1);
  1185.   return(0);
  1186. }
  1187.  
  1188.  
  1189. int find_all_person_matches (person) char *person;
  1190.  
  1191. {
  1192.   Ptr_Rolo_List rptr = Begin_Rlist;        
  1193.   int count = 0;
  1194.   while (rptr != 0) {
  1195.     unset_matched(rptr);
  1196.     if (person_match(person,get_entry(rptr))) {
  1197.        set_matched(rptr);
  1198.        count++;
  1199.     }
  1200.     rptr = get_next_link(rptr);
  1201.   }
  1202.   return(count);
  1203. }
  1204.  
  1205.  
  1206. look_for_person (person) char *person; 
  1207.  
  1208. /* search against Name and Company over the rolodex.  If a match is found */
  1209. /* display the entry and give the user a choice of what to do next. */
  1210.  
  1211. {
  1212.   Ptr_Rolo_List rptr;        
  1213.   int found = 0,result,nmatches;
  1214.   static displayed_menu = 0;
  1215.   char *response;
  1216.   
  1217.   rptr = Begin_Rlist;        
  1218.   while (rptr != 0) {        
  1219.     if (person_match(person,get_entry(rptr))) {
  1220.        clear_the_screen();
  1221.        display_entry(get_entry(rptr));
  1222.        if (!found) {
  1223.           nmatches = find_all_person_matches(person);
  1224.           if (nmatches > 1) {
  1225.              printf (
  1226.                 "There are %d other entries which match '%s'\n\n",
  1227.                 nmatches - 1, person
  1228.               );
  1229.           }
  1230.        }
  1231.        found = 1;
  1232.        try_again :
  1233.        if (!displayed_menu) cathelpfile(libdir("poptionmenu"),0,0);
  1234.        displayed_menu = 1;
  1235.        menu_match (
  1236.             &result,
  1237.             &response,
  1238.             "Select option (? for help): ",
  1239.             0,1,1,1,6,
  1240.             "Continue",P_CONTINUE,
  1241.             "",P_CONTINUE,
  1242.             "Next",P_NEXT_PERSON,
  1243.             "\\",P_ABORT,
  1244.             "Help",P_HELP,
  1245.             "?",P_HELP
  1246.          );
  1247.        switch (result) {
  1248.          case P_CONTINUE :
  1249.            break;
  1250.          case P_NEXT_PERSON :
  1251.            return;
  1252.            break;
  1253.          case P_ABORT :
  1254.            roloexit(0);
  1255.            break;
  1256.          case P_HELP :
  1257.            cathelpfile(libdir("poptionshelp"),"person search options",1);
  1258.            goto try_again;
  1259.          default :
  1260.            fprintf(stderr,"Impossible return from menu_match\n");
  1261.            exit(-1);
  1262.        }
  1263.     }
  1264.     rptr = get_next_link(rptr);
  1265.   }
  1266.   if (!found) {
  1267.      fprintf(stderr,"\nNo entry found for '%s'\n\n",person);
  1268.      sleep(2);
  1269.   }
  1270.   else {
  1271.      printf("No further matches for '%s'\n",person);
  1272.      sleep(2);
  1273.   }   
  1274. }
  1275.  
  1276.  
  1277. print_people ()
  1278.  
  1279. {
  1280.   int index;
  1281.   char *person;
  1282.   index = 1;
  1283.   while (T) {
  1284.      if (0 == (person = non_option_arg(index++))) break;
  1285.      look_for_person(person);
  1286.   }
  1287. }
  1288.  
  1289.  
  1290. interactive_rolo ()
  1291.  
  1292. /* Top level of the iteractive rolodex.  This code is just a big switch */
  1293. /* which passes responsibility off to various routines in 'operations.c' */
  1294. /* and 'update.c' */
  1295.  
  1296. {
  1297.  
  1298.   int result,rval,field_index;
  1299.   char *response,*field_name,*search_string;
  1300.  
  1301.   fprintf(stdout,"\n\nTMC ROLODEX, Version %s\n\n\n",VERSION);        
  1302.   
  1303.   while (1) {        
  1304.         
  1305.     cathelpfile(libdir("mainmenu"),0,0);
  1306.     rval = menu_match (
  1307.          &result,
  1308.          &response,
  1309.          "Select option (? for help): ",
  1310.          0,1,0,1,7,
  1311.          "+",M_ADD,
  1312.          "%",M_PERUSE,
  1313.          "\\",M_EXIT,
  1314.          "?",M_HELP,
  1315.          "*",M_SAVE,
  1316.          "$",M_SEARCH_BY_OTHER,
  1317.          "!",M_PRINT_TO_LASER_PRINTER
  1318.       );
  1319.       
  1320.     switch (rval) {
  1321.         
  1322.       case MENU_AMBIGUOUS :
  1323.       case MENU_ERROR :
  1324.         fprintf(stderr,"Impossible return 1 from main menu_match\n");
  1325.         exit(-1);
  1326.         break;
  1327.         
  1328.       case MENU_NO_MATCH :
  1329.         response = copystr(response);
  1330.         rolo_search_mode((int) R_NAME,Field_Names[(int) R_NAME],response);
  1331.         break;
  1332.         
  1333.       case MENU_MATCH :
  1334.         
  1335.         switch (result) {
  1336.           case M_ADD :
  1337.             rolo_add();
  1338.             break;
  1339.           case M_SEARCH_BY_OTHER :
  1340.             if ((-1 == select_field_to_search_by(&field_index,&field_name)) ||
  1341.                 (0 == (search_string = select_search_string()))) {
  1342.                break;
  1343.             }
  1344.             rolo_search_mode(field_index,field_name,search_string);
  1345.             break;
  1346.           case M_PRINT_TO_LASER_PRINTER :
  1347.             fprintf(stderr,"Not implemented\n");
  1348.             sleep(1);
  1349.             break;
  1350.           case M_PERUSE :
  1351.             rolo_peruse_mode(Begin_Rlist);
  1352.             break;
  1353.           case M_EXIT :
  1354.             save_and_exit(0);
  1355.             break;
  1356.           case M_SAVE :
  1357.             if (changed) {
  1358.                save_to_disk();
  1359.                sleep(1);
  1360.             }
  1361.             else {
  1362.                printf("No changes to be saved...\n");
  1363.                sleep(2);
  1364.             }
  1365.             break;
  1366.           case M_HELP :
  1367.             cathelpfile(libdir("moptionhelp"),"top level menu",1);
  1368.             any_char_to_continue();
  1369.             break;
  1370.           default :
  1371.             fprintf(stderr,"Impossible result from menu_match...\n");
  1372.             save_and_exit(-1);
  1373.         }
  1374.         break;
  1375.             
  1376.       case MENU_EOF :
  1377.         user_eof();
  1378.         break;
  1379.         
  1380.       default :
  1381.         fprintf(stderr,"Impossible return 2 from menu_match\n");
  1382.         save_and_exit(-1);
  1383.         
  1384.     }
  1385.     
  1386.     clear_the_screen();
  1387.     
  1388.   }
  1389.  
  1390. }
  1391. SHAR_EOF
  1392. if test 6785 -ne "`wc -c < 'options.c'`"
  1393. then
  1394.     echo shar: error transmitting "'options.c'" '(should have been 6785 characters)'
  1395. fi
  1396. fi
  1397. echo shar: extracting "'rlist.c'" '(2445 characters)'
  1398. if test -f 'rlist.c'
  1399. then
  1400.     echo shar: will not over-write existing file "'rlist.c'"
  1401. else
  1402. cat << \SHAR_EOF > 'rlist.c'
  1403. #include "datadef.h"
  1404.  
  1405.  
  1406. int rlength (rlist) Ptr_Rolo_List rlist;
  1407. {
  1408.   return((rlist == 0) ? 0 : 1 + rlength(get_next_link(rlist)));
  1409. }  
  1410.   
  1411.  
  1412. Ptr_Rolo_List new_link_with_entry ()
  1413. {
  1414.   Ptr_Rolo_List newlink;        
  1415.   Ptr_Rolo_Entry newentry;
  1416.   newlink = (Ptr_Rolo_List) rolo_emalloc(sizeof(Rolo_List));
  1417.   unset_matched(newlink);
  1418.   newentry = (Ptr_Rolo_Entry) rolo_emalloc(sizeof(Rolo_Entry));
  1419.   set_n_others(newentry,0);        
  1420.   newentry -> other_fields = 0;
  1421.   set_entry(newlink,newentry);
  1422.   return(newlink);
  1423. }
  1424.  
  1425.  
  1426. rolo_insert (link,compare) Ptr_Rolo_List link; int (*compare)();
  1427.  
  1428. {
  1429.   Ptr_Rolo_List rptr;        
  1430.         
  1431.   if (Begin_Rlist == 0) {
  1432.      Begin_Rlist = link;
  1433.      End_Rlist = link;
  1434.      set_prev_link(link,0);
  1435.      set_next_link(link,0);
  1436.      return;
  1437.   }
  1438.   
  1439.   /* find the element it goes before, alphabetically, and insert it */
  1440.  
  1441.   rptr = Begin_Rlist;
  1442.   while (rptr != 0) {
  1443.     if (1 == (*compare)(rptr,link)) {
  1444.        set_prev_link(link,get_prev_link(rptr));
  1445.        set_next_link(link,rptr);
  1446.        if (get_prev_link(rptr) != 0) 
  1447.           set_next_link(get_prev_link(rptr),link);
  1448.        else
  1449.           Begin_Rlist = link;
  1450.        set_prev_link(rptr,link);
  1451.        return;
  1452.     }
  1453.     rptr = get_next_link(rptr);
  1454.   }
  1455.  
  1456.   /* it goes at the end */
  1457.   
  1458.   set_next_link(End_Rlist,link);
  1459.   set_prev_link(link,End_Rlist);
  1460.   set_next_link(link,0);
  1461.   End_Rlist = link;
  1462.   return;
  1463.  
  1464. }
  1465.  
  1466.  
  1467. rolo_delete (link) Ptr_Rolo_List link;
  1468.  
  1469. {
  1470.   if (get_next_link(link) == 0 && get_prev_link(link) == 0) {
  1471.      Begin_Rlist = 0;
  1472.      End_Rlist = 0;
  1473.      return;
  1474.   }
  1475.  
  1476.   if (get_prev_link(link) == 0) {
  1477.      Begin_Rlist = get_next_link(link);
  1478.      set_prev_link(Begin_Rlist,0);
  1479.      return;
  1480.   }
  1481.  
  1482.   if (get_next_link(link) == 0) {
  1483.      End_Rlist = get_prev_link(link);
  1484.      set_next_link(End_Rlist,0);
  1485.      return;
  1486.   }
  1487.  
  1488.   set_next_link(get_prev_link(link),get_next_link(link));
  1489.   set_prev_link(get_next_link(link),get_prev_link(link));
  1490.   return;
  1491.  
  1492. }
  1493.  
  1494.  
  1495. compare_links (l1,l2) Ptr_Rolo_List l1,l2;
  1496.  
  1497. {
  1498.   Ptr_Rolo_Entry e1,e2;        
  1499.   char *n1,*n2;
  1500.   e1 = get_entry(l1);        
  1501.   e2 = get_entry(l2);        
  1502.   n1 = get_basic_rolo_field((int) R_NAME,e1);
  1503.   n2 = get_basic_rolo_field((int) R_NAME,e2);
  1504.   return(nocase_compare(n1,strlen(n1),n2,strlen(n2)));
  1505. }  
  1506.   
  1507.  
  1508. rolo_reorder ()
  1509. {
  1510.   Ptr_Rolo_List rptr,oldlink;
  1511.   rptr = Begin_Rlist;
  1512.   Begin_Rlist = 0;
  1513.   while (rptr != 0) {
  1514.     oldlink = get_next_link(rptr);
  1515.     rolo_insert(rptr,compare_links);
  1516.     rptr = oldlink;
  1517.   }
  1518. }
  1519.  
  1520.  
  1521. SHAR_EOF
  1522. if test 2445 -ne "`wc -c < 'rlist.c'`"
  1523. then
  1524.     echo shar: error transmitting "'rlist.c'" '(should have been 2445 characters)'
  1525. fi
  1526. fi
  1527. echo shar: extracting "'rolo.c'" '(8738 characters)'
  1528. if test -f 'rolo.c'
  1529. then
  1530.     echo shar: will not over-write existing file "'rolo.c'"
  1531. else
  1532. cat << \SHAR_EOF > 'rolo.c'
  1533. #include <sys/file.h>
  1534. #include <stdio.h>
  1535. #include <ctype.h>
  1536. #include <sgtty.h>
  1537. #include <signal.h>
  1538. #include <curses.h>
  1539. #include <pwd.h>
  1540.  
  1541. #include "sys5.h"
  1542.  
  1543. #ifdef TMC
  1544. #include <ctools.h>
  1545. #else
  1546. #include "ctools.h"
  1547. #endif
  1548. #include "args.h"
  1549. #include "menu.h"
  1550. #include "mem.h"
  1551.  
  1552. #include "rolofiles.h"
  1553. #include "rolodefs.h"
  1554. #include "datadef.h"
  1555.  
  1556.  
  1557. static char rolodir[DIRPATHLEN];        /* directory where rolo data is */
  1558. static char filebuf[DIRPATHLEN];        /* stores result of homedir() */
  1559.  
  1560. int changed = 0;
  1561. int reorder_file = 0;
  1562. int rololocked = 0;
  1563. int in_search_mode = 0;
  1564.  
  1565.  
  1566. char *rolo_emalloc (size) int size;
  1567.  
  1568. /* error handling memory allocator */
  1569.  
  1570. {
  1571.   char *rval;        
  1572.   if (0 == (rval = malloc(size))) {        
  1573.      fprintf(stderr,"Fatal error:  out of memory\n");
  1574.      save_and_exit(-1);
  1575.   }
  1576.   return(rval);
  1577. }  
  1578.  
  1579.         
  1580. char *copystr (s) char *s;
  1581.  
  1582. /* memory allocating string copy routine */
  1583.  
  1584.  
  1585. {
  1586.  char *copy;        
  1587.  if (s == 0) return(0);
  1588.  copy = rolo_emalloc(strlen(s) + 1);
  1589.  strcpy(copy,s);
  1590.  return(copy);
  1591. }
  1592.  
  1593.  
  1594. char *timestring ()
  1595.  
  1596. /* returns a string timestamp */
  1597.  
  1598. {
  1599.   char *s;        
  1600.   long timeval;
  1601.   time(&timeval);
  1602.   s = ctime(&timeval);  
  1603.   s[strlen(s) - 1] = '\0';
  1604.   return(copystr(s));
  1605. }  
  1606.   
  1607.  
  1608. user_interrupt ()
  1609.  
  1610. /* if the user hits C-C (we assume he does it deliberately) */
  1611.  
  1612. {
  1613.   unlink(homedir(ROLOLOCK));
  1614.   fprintf(stderr,"\nAborting rolodex, no changes since last save recorded\n");
  1615.   exit(-1);  
  1616. }  
  1617.  
  1618.  
  1619. user_eof ()
  1620.  
  1621. /* if the user hits C-D */
  1622.  
  1623. {
  1624.   unlink(homedir(ROLOLOCK));        
  1625.   fprintf(stderr,"\nUnexpected EOF on terminal. Saving rolodex and exiting\n");
  1626.   save_and_exit(-1);        
  1627. }
  1628.  
  1629.  
  1630. roloexit (rval) int rval;
  1631. {
  1632.   if (rololocked) unlink(homedir(ROLOLOCK));        
  1633.   exit(rval);
  1634. }  
  1635.  
  1636.  
  1637. save_to_disk ()
  1638.  
  1639. /* move the old rolodex to a backup, and write out the new rolodex and */
  1640. /* a copy of the new rolodex (just for safety) */
  1641.  
  1642. {
  1643.   FILE *tempfp,*copyfp;        
  1644.   char d1[DIRPATHLEN], d2[DIRPATHLEN];
  1645.   int r;
  1646.         
  1647.   tempfp = fopen(homedir(ROLOTEMP),"w");
  1648.   copyfp = fopen(homedir(ROLOCOPY),"w");
  1649.   if (tempfp == NULL || copyfp == NULL) {
  1650.      fprintf(stderr,"Unable to write rolodex...\n");
  1651.      fprintf(stderr,"Any changes made have not been recorded\n");
  1652.      roloexit(-1);
  1653.   }
  1654.   write_rolo(tempfp,copyfp);
  1655.   fclose(tempfp);
  1656.   fclose(copyfp);
  1657.   if (rename(strcpy(d1,homedir(ROLODATA)),strcpy(d2,homedir(ROLOBAK))) ||
  1658.       rename(strcpy(d1,homedir(ROLOTEMP)),strcpy(d2,homedir(ROLODATA)))) {
  1659.      fprintf(stderr,"Rename failed.  Revised rolodex is in %s\n",ROLOCOPY);
  1660.      roloexit(-1);
  1661.   }
  1662.   printf("Rolodex saved\n");
  1663.   sleep(1);
  1664.   changed = 0;
  1665. }
  1666.   
  1667.  
  1668. save_and_exit (rval) int rval;
  1669. {
  1670.   if (changed) save_to_disk();        
  1671.   roloexit(rval);        
  1672. }
  1673.  
  1674.  
  1675. extern struct passwd *getpwnam();
  1676.  
  1677. char *home_directory (name) char *name;
  1678. {
  1679.   struct passwd *pwentry;
  1680.   if (0 == (pwentry = getpwnam(name))) return("");
  1681.   return(pwentry -> pw_dir);
  1682. }        
  1683.  
  1684.  
  1685. char *homedir (filename) char *filename;
  1686.  
  1687. /* e.g., given "rolodex.dat", create "/u/massar/rolodex.dat" */
  1688. /* rolodir generally the user's home directory but could be someone else's */
  1689. /* home directory if the -u option is used. */
  1690.  
  1691. {
  1692.   nbuffconcat(filebuf,3,rolodir,"/",filename);
  1693.   return(filebuf);
  1694. }
  1695.  
  1696.  
  1697. char *libdir (filename) char *filename;
  1698.  
  1699. /* return a full pathname into the rolodex library directory */
  1700. /* the string must be copied if it is to be saved! */
  1701.  
  1702. {
  1703.   nbuffconcat(filebuf,3,ROLOLIB,"/",filename);        
  1704.   return(filebuf);        
  1705. }
  1706.  
  1707.  
  1708. rolo_only_to_read () 
  1709. {
  1710.   return(option_present(SUMMARYFLAG) || n_non_option_args() > 0);
  1711. }
  1712.  
  1713.  
  1714. locked_action () 
  1715. {
  1716.   if (option_present(OTHERUSERFLAG)) {        
  1717.      fprintf(stderr,"Someone else is modifying that rolodex, sorry\n");
  1718.      exit(-1);
  1719.   }
  1720.   else {
  1721.      cathelpfile(libdir("lockinfo"),"locked rolodex",0);
  1722.      exit(-1);
  1723.   }
  1724. }  
  1725.   
  1726.  
  1727. main (argc,argv) int argc; char *argv[];
  1728.  
  1729. {
  1730.     int fd,in_use,read_only,rolofd;
  1731.     Bool not_own_rolodex;        
  1732.     char *user;
  1733.     FILE *tempfp;
  1734.     
  1735.     clearinit();
  1736.     clear_the_screen();
  1737.     
  1738.     /* parse the options and arguments, if any */
  1739.     
  1740.     switch (get_args(argc,argv,T,T)) {
  1741.         case ARG_ERROR : 
  1742.           roloexit(-1);
  1743.         case NO_ARGS :
  1744.           break;
  1745.         case ARGS_PRESENT :
  1746.           if (ALL_LEGAL != legal_options(LEGAL_OPTIONS)) {
  1747.                 fprintf(stderr,"illegal option\nusage: %s\n",USAGE);
  1748.                 roloexit(-1);
  1749.           }
  1750.     }
  1751.     
  1752.     /* find the directory in which the rolodex file we want to use is */
  1753.     
  1754.     not_own_rolodex = option_present(OTHERUSERFLAG);        
  1755.     if (not_own_rolodex) {
  1756.        if (NIL == (user = option_arg(OTHERUSERFLAG,1)) || 
  1757.            n_option_args(OTHERUSERFLAG) != 1) {
  1758.           fprintf(stderr,"Illegal syntax using -u option\nusage: %s\n",USAGE);
  1759.           roloexit(-1);
  1760.        }
  1761.     }        
  1762.     else {
  1763.        if (0 == (user = getenv("HOME"))) {
  1764.           fprintf(stderr,"Cant find your home directory, no HOME\n");
  1765.           roloexit(-1);
  1766.        }
  1767.     }
  1768.     
  1769.     if (not_own_rolodex) {
  1770.        strcpy(rolodir,home_directory(user));
  1771.        if (*rolodir == '\0') {
  1772.           fprintf(stderr,"No user %s is known to the system\n",user);
  1773.           roloexit(-1);
  1774.        }
  1775.     }
  1776.     else strcpy(rolodir,user);
  1777.     
  1778.     /* is the rolodex readable? */
  1779.     
  1780.     if (0 != access(homedir(ROLODATA),R_OK)) {
  1781.         
  1782.        /* No.  if it exists and we cant read it, that's an error */
  1783.         
  1784.        if (0 == access(homedir(ROLODATA),F_OK)) { 
  1785.           fprintf(stderr,"Cant access rolodex data file to read\n");
  1786.           roloexit(-1);
  1787.        }
  1788.        
  1789.        /* if it doesn't exist, should we create one? */
  1790.        
  1791.        if (option_present(OTHERUSERFLAG)) {
  1792.           fprintf(stderr,"No rolodex file belonging to %s found\n",user);
  1793.           roloexit(-1);
  1794.        }
  1795.        
  1796.        /* try to create it */
  1797.        
  1798.        if (-1 == (fd = creat(homedir(ROLODATA),0644))) {
  1799.           fprintf(stderr,"couldnt create rolodex in your home directory\n");
  1800.           roloexit(-1);
  1801.        }
  1802.        
  1803.        else {
  1804.           close(fd);
  1805.           fprintf(stderr,"Creating empty rolodex...\n");
  1806.        }
  1807.  
  1808.     }
  1809.     
  1810.     /* see if someone else is using it */
  1811.     
  1812.     in_use = (0 == access(homedir(ROLOLOCK),F_OK));
  1813.     
  1814.     /* are we going to access the rolodex only for reading? */
  1815.     
  1816.     if (!(read_only = rolo_only_to_read())) {
  1817.     
  1818.        /* No.  Make sure no one else has it locked. */
  1819.         
  1820.        if (in_use) {
  1821.           locked_action();
  1822.        }
  1823.         
  1824.        /* create a lock file.  Catch interrupts so that we can remove */
  1825.        /* the lock file if the user decides to abort */
  1826.        
  1827.        if (!option_present(NOLOCKFLAG)) {
  1828.           if ((fd = open(homedir(ROLOLOCK),O_EXCL|O_CREAT,00200|00400)) < 0) {
  1829.              fprintf(stderr,"unable to create lock file...\n");
  1830.          exit(1);
  1831.       }
  1832.           rololocked = 1;
  1833.           close(fd);
  1834.           signal(SIGINT,user_interrupt);        
  1835.        }
  1836.         
  1837.        /* open a temporary file for writing changes to make sure we can */
  1838.        /* write into the directory */
  1839.        
  1840.        /* when the rolodex is saved, the old rolodex is moved to */
  1841.        /* a '~' file, the temporary is made to be the new rolodex, */
  1842.        /* and a copy of the new rolodex is made */
  1843.        
  1844.        if (NULL == (tempfp = fopen(homedir(ROLOTEMP),"w"))) {
  1845.            fprintf(stderr,"Can't open temporary file to write to\n");
  1846.            roloexit(-1);
  1847.        }        
  1848.        fclose(tempfp);
  1849.     
  1850.     }
  1851.        
  1852.     allocate_memory_chunk(CHUNKSIZE);
  1853.     
  1854.     if (NULL == (rolofd = open(homedir(ROLODATA),O_RDONLY))) {
  1855.         fprintf(stderr,"Can't open rolodex data file to read\n");
  1856.         roloexit(-1);
  1857.     }
  1858.     
  1859.     /* read in the rolodex from disk */
  1860.     /* It should never be out of order since it is written to disk ordered */
  1861.     /* but just in case... */
  1862.     
  1863.     if (!read_only) printf("Reading in rolodex from %s\n",homedir(ROLODATA));
  1864.     read_rolodex(rolofd);
  1865.     close(rolofd);
  1866.     if (!read_only) printf("%d entries listed\n",rlength(Begin_Rlist));
  1867.     if (reorder_file && !read_only) {
  1868.        fprintf(stderr,"Reordering rolodex...\n");
  1869.        rolo_reorder();
  1870.        fprintf(stderr,"Saving reordered rolodex to disk...\n");
  1871.        save_to_disk();
  1872.     }
  1873.        
  1874.     /* the following routines live in 'options.c' */
  1875.     
  1876.     /* -s option.  Prints a short listing of people and phone numbers to */
  1877.     /* standard output */
  1878.     
  1879.     if (option_present(SUMMARYFLAG)) {
  1880.         print_short();
  1881.         exit(0);
  1882.     }
  1883.     
  1884.     /* rolo <name1> <name2> ... */
  1885.     /* print out info about people whose names contain any of the arguments */
  1886.     
  1887.     if (n_non_option_args() > 0) {
  1888.        print_people();
  1889.        exit(0);
  1890.     }
  1891.     
  1892.     /* regular rolodex program */
  1893.     
  1894.     interactive_rolo();
  1895.     exit(0);
  1896.     
  1897. }    
  1898. SHAR_EOF
  1899. if test 8738 -ne "`wc -c < 'rolo.c'`"
  1900. then
  1901.     echo shar: error transmitting "'rolo.c'" '(should have been 8738 characters)'
  1902. fi
  1903. fi
  1904. echo shar: extracting "'rolodefs.h'" '(262 characters)'
  1905. if test -f 'rolodefs.h'
  1906. then
  1907.     echo shar: will not over-write existing file "'rolodefs.h'"
  1908. else
  1909. cat << \SHAR_EOF > 'rolodefs.h'
  1910. #define VERSION "2.0"
  1911.  
  1912. #define CHUNKSIZE 100000        /* storage size for holding data file */
  1913.  
  1914. #define NOLOCKFLAG 'l'
  1915. #define SUMMARYFLAG 's'
  1916. #define OTHERUSERFLAG 'u'
  1917.  
  1918. #define LEGAL_OPTIONS "lsu"
  1919. #define USAGE "rolo [ person1 person2 ...] [ -l -s -u user ] "
  1920. SHAR_EOF
  1921. if test 262 -ne "`wc -c < 'rolodefs.h'`"
  1922. then
  1923.     echo shar: error transmitting "'rolodefs.h'" '(should have been 262 characters)'
  1924. fi
  1925. fi
  1926. echo shar: extracting "'rolofiles.h'" '(280 characters)'
  1927. if test -f 'rolofiles.h'
  1928. then
  1929.     echo shar: will not over-write existing file "'rolofiles.h'"
  1930. else
  1931. cat << \SHAR_EOF > 'rolofiles.h'
  1932. #define ROLOBAK ".rolodex~"
  1933. #define ROLODATA ".rolodex.dat"
  1934. #define ROLOPRINT "roloprint.text"
  1935. #define ROLOLOCK ".rolodexdata.lock"
  1936. #define ROLOTEMP ".rolotemp"
  1937. #define ROLOCOPY ".rolocopy"
  1938.  
  1939. /* This is now defined in the Makefile */
  1940.  
  1941. /*  #define ROLOLIB "/usr/local/lib/rolo"  */
  1942. SHAR_EOF
  1943. if test 280 -ne "`wc -c < 'rolofiles.h'`"
  1944. then
  1945.     echo shar: error transmitting "'rolofiles.h'" '(should have been 280 characters)'
  1946. fi
  1947. fi
  1948. echo shar: extracting "'search.c'" '(9108 characters)'
  1949. if test -f 'search.c'
  1950. then
  1951.     echo shar: will not over-write existing file "'search.c'"
  1952. else
  1953. cat << \SHAR_EOF > 'search.c'
  1954. #include <stdio.h>
  1955. #include <ctype.h>
  1956.  
  1957. #include "sys5.h"
  1958.  
  1959. #ifdef TMC
  1960. #include <ctools.h>
  1961. #else
  1962. #include "ctools.h"
  1963. #endif
  1964. #include "args.h"
  1965. #include "menu.h"
  1966. #include "mem.h"
  1967.  
  1968. #include "rolofiles.h"
  1969. #include "rolodefs.h"
  1970. #include "datadef.h"
  1971. #include "choices.h"
  1972.  
  1973.  
  1974. char *select_search_string ()
  1975.  
  1976. /* returns 0 if user wants to quit, otherwise returns a user-provided string */
  1977.  
  1978. {
  1979.   int rval;        
  1980.   char *response;
  1981.   rval = rolo_menu_data_help_or_abort (        
  1982.               "Enter string to search for: ",
  1983.               "searchstringhelp",
  1984.               "string to search for",
  1985.               &response
  1986.           );
  1987.   switch (rval) {          
  1988.     case MENU_ABORT :
  1989.       return(0);
  1990.       break;
  1991.     case MENU_DATA :
  1992.       return(copystr(response));
  1993.       break;
  1994.   }
  1995. }  
  1996.   
  1997.  
  1998. select_field_to_search_by (ptr_index,ptr_name) int *ptr_index; char **ptr_name;
  1999.  
  2000. /* returns -1 if the user wishes to abort, otherwise returns 0. */
  2001. /* if the user wishes to search by a user-defined field, *ptr_index is OTHER */
  2002. /* and *ptr_name is the user-provided name of the field. */
  2003.  
  2004. {
  2005.   char *response;
  2006.   int nchoices = N_BASIC_FIELDS;
  2007.   int field_index,rval;
  2008.   
  2009.   redo :
  2010.   
  2011.   /* list out each basic field that the user can search by.   The user is */
  2012.   /* also given an option to search by a user-provided field.   At the */
  2013.   /* moment you cannot search by 'Date Updated' */
  2014.   
  2015.   display_field_names();  
  2016.   
  2017.   reask :
  2018.   
  2019.   rval = rolo_menu_number_help_or_abort (
  2020.        "Number of item to search by? ",
  2021.        1,nchoices,&field_index
  2022.     );
  2023.     
  2024.   switch (rval) {
  2025.         
  2026.     case MENU_ABORT :
  2027.       return(-1);
  2028.       break;
  2029.       
  2030.     case MENU_HELP :
  2031.       cathelpfile(libdir("fieldsearchhelp"),"entering search field",1);
  2032.       any_char_to_continue();
  2033.       goto redo;
  2034.       break;
  2035.       
  2036.     case MENU_DATA :
  2037.     
  2038.       if (field_index != nchoices) {
  2039.          *ptr_index = field_index - 1;
  2040.          *ptr_name = copystr(Field_Names[*ptr_index]);
  2041.          return(0);
  2042.       }
  2043.       
  2044.       /* the user wants to search by a user-specified field */
  2045.       
  2046.       else {
  2047.         
  2048.          reask2 :
  2049.         
  2050.          rval = rolo_menu_data_help_or_abort (
  2051.                     "Name of user-defined field? ",
  2052.                     "userfieldhelp",
  2053.                     "name of user field to search by",
  2054.                     &response
  2055.                  );
  2056.          switch (rval) {
  2057.            case MENU_ABORT :
  2058.              return(-1);
  2059.              break;
  2060.            case MENU_DATA :
  2061.              *ptr_index = OTHER;
  2062.              *ptr_name = copystr(response);           
  2063.              return(0);         
  2064.              break;
  2065.          }
  2066.       }
  2067.       break;
  2068.   }
  2069.   
  2070. }  
  2071.       
  2072.  
  2073. match_by_name_or_company (search_string,sslen) char *search_string; int sslen;
  2074.  
  2075. {
  2076.   char *name,*company;
  2077.   Ptr_Rolo_Entry entry;        
  2078.   Ptr_Rolo_List rlist;
  2079.   int count = 0;
  2080.   
  2081.   rlist = Begin_Rlist;
  2082.   while (rlist != 0) {  
  2083.     entry = get_entry(rlist);
  2084.     name = get_basic_rolo_field((int) R_NAME,entry);
  2085.     company = get_basic_rolo_field((int) R_COMPANY,entry);
  2086.     if (strncsearch(name,strlen(name),search_string,sslen) ||
  2087.         strncsearch(company,strlen(company),search_string,sslen)) {
  2088.        set_matched(rlist);
  2089.        count++;
  2090.     }
  2091.   }
  2092.   return(count);
  2093.   
  2094. }
  2095.  
  2096.  
  2097. match_link (rlink,field_index,field_name,fnlen,search_string,sslen)
  2098.  
  2099.   /* if a match is present, sets the 'matched' field in the link, and */
  2100.   /* returns 1, otherwise returns 0. */
  2101.  
  2102.   Ptr_Rolo_List rlink;
  2103.   int field_index;
  2104.   char *field_name;
  2105.   int fnlen;
  2106.   char *search_string;
  2107.   int sslen;
  2108.   
  2109. {
  2110.   Ptr_Rolo_Entry entry;        
  2111.   char *field;
  2112.   char name[100];
  2113.   int j;
  2114.         
  2115.   entry = get_entry(rlink);
  2116.   
  2117.   if (field_index == OTHER) {
  2118.      for (j = 0; j < get_n_others(entry); j++) {
  2119.          field = get_other_field(j,entry);
  2120.          while (*field != ':') *field++;
  2121.          *field = '\0';
  2122.          remove_excess_blanks(name,get_other_field(j,entry));
  2123.          *field++ = ':';
  2124.          if (0 != nocase_compare(name,strlen(name),field_name,fnlen)) {
  2125.             continue;
  2126.          }
  2127.          if (strncsearch(field,strlen(field),search_string,sslen)) {
  2128.             set_matched(rlink);
  2129.             return(1);
  2130.          }
  2131.      }
  2132.      return(0);
  2133.   }
  2134.   else {
  2135.      field = get_basic_rolo_field(field_index,entry);
  2136.      if (strncsearch(field,strlen(field),search_string,sslen)) {
  2137.         set_matched(rlink);
  2138.         return(1);
  2139.      }
  2140.      return(0);
  2141.   }
  2142.  
  2143. }
  2144.  
  2145.  
  2146. find_all_matches (field_index,field_name,search_string,ptr_first_match) 
  2147.  
  2148.   /* mark every entry in the rolodex which matches against the search_string */
  2149.   /* If the search_string is a substring of the data in the given field then */
  2150.   /* that is a match.  Return the number of matches.  If there are any */
  2151.   /* matches *ptr_first_match will contain the first matching link. */
  2152.  
  2153.   int field_index;
  2154.   char *field_name, *search_string;
  2155.   Ptr_Rolo_List *ptr_first_match;
  2156.  
  2157. {  
  2158.   char buffer[100];    
  2159.   int fnlen,sslen;
  2160.   int count = 0;
  2161.   Ptr_Rolo_List rlist = Begin_Rlist;
  2162.   
  2163.   remove_excess_blanks(buffer,field_name);
  2164.   fnlen = strlen(buffer);
  2165.   sslen = strlen(search_string);
  2166.   
  2167.   while (rlist != 0) {  
  2168.     unset_matched(rlist);
  2169.     if (match_link(rlist,field_index,buffer,fnlen,search_string,sslen)) {
  2170.        if (count++ == 0) *ptr_first_match = rlist;
  2171.     }
  2172.     rlist = get_next_link(rlist);
  2173.   }    
  2174.   
  2175.   return(count);
  2176.   
  2177. }
  2178.  
  2179.  
  2180. rolo_search_mode (field_index,field_name,search_string)
  2181.  
  2182.   int field_index;
  2183.   char *field_name;
  2184.   char *search_string;
  2185.  
  2186. {
  2187.   int rval,n,j,menuval,ival;
  2188.   char *response;
  2189.   Ptr_Rolo_List first_match,rmatch,rlist;
  2190.  
  2191.   /* mark every entry in the rolodex that satisfies the search criteria */
  2192.   /* and return the number of items so marked. */
  2193.   
  2194.   in_search_mode = 1;
  2195.   n = find_all_matches(field_index,field_name,search_string,&first_match);
  2196.  
  2197.   if (n == 0) {
  2198.      printf (
  2199.          "No match found for search string '%s' for field '%s'\n",
  2200.          search_string,
  2201.          field_name
  2202.       );
  2203.       sleep(2);
  2204.       goto rtn;
  2205.   }
  2206.  
  2207.   /* if the match is unique, just display the entry. */
  2208.   
  2209.   else if (n == 1) {
  2210.      display_entry(get_entry(first_match));
  2211.      switch (entry_action(first_match)) {
  2212.        case E_CONTINUE :
  2213.          printf("No further matches...\n");
  2214.          sleep(2);
  2215.          break;
  2216.        default :
  2217.          break;
  2218.      }
  2219.      goto rtn;
  2220.   }
  2221.  
  2222.   /* if there are too many matches to itemize them on a single small */
  2223.   /* screen, tell the user that there are lots of matches and suggest */
  2224.   /* he specify a better search string, but give him the option of */
  2225.   /* iterating through every match. */
  2226.   
  2227.   else if (n > MAXMATCHES) {
  2228.      clear_the_screen();
  2229.      printf("There are %d entries that match '%s' !\n",n,search_string);
  2230.      printf("Type 'v' to view them one by one,\n");
  2231.      printf("or '\\' to abort and enter a more specific search string: ");
  2232.      rval = rolo_menu_data_help_or_abort (
  2233.                  "","manymatchhelp","many matching entries",&response
  2234.               );
  2235.      if (rval == MENU_ABORT) goto rtn;              
  2236.      display_list_of_entries(Begin_Rlist);
  2237.      goto rtn;
  2238.   }
  2239.  
  2240.   /* there are a small number of matching entries.  List the name of each */
  2241.   /* matching entry and let the user select which one he wants to view, */
  2242.   /* or whether he wants to iterate through each matching entry. */
  2243.   
  2244.   else {
  2245.      relist :
  2246.      summarize_entry_list(Begin_Rlist,search_string);
  2247.      cathelpfile(libdir("pickentrymenu"),0,0);  
  2248.      rval = menu_match (
  2249.           &menuval,&response,
  2250.           ": ",
  2251.           0,1,0,1,4,
  2252.           "\\",S_ABORT,
  2253.           "?",S_HELP,
  2254.           "Help",S_HELP,
  2255.           "",S_SCAN_ONE_BY_ONE
  2256.        );
  2257.      switch (rval) {    
  2258.        case MENU_MATCH :
  2259.          switch (menuval) {
  2260.            case S_HELP :
  2261.              cathelpfile(libdir("pickentryhelp"),"selecting entry to view",1);
  2262.              any_char_to_continue();
  2263.              goto relist;
  2264.              break;
  2265.            case S_ABORT :
  2266.              goto rtn;
  2267.              break;
  2268.            case S_SCAN_ONE_BY_ONE :
  2269.              display_list_of_entries(Begin_Rlist);
  2270.              goto rtn;
  2271.              break;
  2272.          }
  2273.          break;
  2274.          
  2275.        /* make sure the user entered a valid integer, ival */
  2276.        /* if so, find the ivalth entry marked as matched in the rolodex */
  2277.        /* and display it. */
  2278.          
  2279.        case MENU_NO_MATCH : 
  2280.          ival = str_to_pos_int(response,1,n);
  2281.          if (ival < 0) {
  2282.             printf("Not a valid number... Please try again\n");
  2283.             sleep(2);
  2284.             goto relist;
  2285.          }
  2286.          rlist = Begin_Rlist;
  2287.          for (j = 0; j < ival; j++) {
  2288.              while (rlist != 0) {
  2289.                if (get_matched(rmatch = rlist)) break;
  2290.                rlist = get_next_link(rlist);
  2291.              }
  2292.              if (rlist != 0) rlist = get_next_link(rlist);                
  2293.          }
  2294.          display_entry(get_entry(rmatch));
  2295.          switch (entry_action(rmatch)) {
  2296.            case E_CONTINUE :
  2297.            case E_PREV :
  2298.              goto relist;
  2299.              break;
  2300.            default :
  2301.              goto rtn;
  2302.              break;
  2303.          }
  2304.          break;
  2305.      }
  2306.   }
  2307.  
  2308.   rtn :
  2309.   in_search_mode = 0;
  2310.   
  2311. }
  2312. SHAR_EOF
  2313. if test 9108 -ne "`wc -c < 'search.c'`"
  2314. then
  2315.     echo shar: error transmitting "'search.c'" '(should have been 9108 characters)'
  2316. fi
  2317. fi
  2318. echo shar: extracting "'update.c'" '(6022 characters)'
  2319. if test -f 'update.c'
  2320. then
  2321.     echo shar: will not over-write existing file "'update.c'"
  2322. else
  2323. cat << \SHAR_EOF > 'update.c'
  2324. #include <stdio.h>
  2325. #include <ctype.h>
  2326.  
  2327. #include "sys5.h"
  2328.  
  2329. #ifdef TMC
  2330. #include <ctools.h>
  2331. #else
  2332. #include "ctools.h"
  2333. #endif
  2334. #include "args.h"
  2335. #include "menu.h"
  2336. #include "mem.h"
  2337.  
  2338. #include "rolofiles.h"
  2339. #include "rolodefs.h"
  2340. #include "datadef.h"
  2341. #include "choices.h"
  2342.  
  2343.  
  2344. char *get_new_value () 
  2345. {
  2346.   char buffer[200];
  2347.   int rval;
  2348.   switch (rval = getline(stdin,buffer,199)) {
  2349.     case AT_EOF :
  2350.       user_eof();
  2351.       break;
  2352.     case TOO_MANY_CHARS :
  2353.       fprintf(stderr,"Line too long, truncated...\n");
  2354.       sleep(1);
  2355.       break;
  2356.     default :
  2357.       if ('\\' == *buffer && rval == 1) return(0);
  2358.       break;
  2359.   }
  2360.   return(copystr(buffer));
  2361. }  
  2362.   
  2363.  
  2364. Ptr_Rolo_Entry copy_entry (entry) Ptr_Rolo_Entry entry;
  2365. {
  2366.   Ptr_Rolo_Entry new_entry;        
  2367.   int j,n;        
  2368.   char **otherfields;
  2369.   
  2370.   new_entry = (Ptr_Rolo_Entry) rolo_emalloc(sizeof(Rolo_Entry));
  2371.   
  2372.   /* copy the basic fields, but get a new timestamp */
  2373.   
  2374.   for (j = 0; j < N_BASIC_FIELDS - 1; j++) {
  2375.       set_basic_rolo_field(j,new_entry,copystr(get_basic_rolo_field(j,entry)));
  2376.   }
  2377.   set_basic_rolo_field(N_BASIC_FIELDS - 1,new_entry,timestring());
  2378.   
  2379.   /* copy the user-defined fields, if necessary */
  2380.   
  2381.   set_n_others(new_entry,n = get_n_others(entry));
  2382.   if (n > 0) {
  2383.      otherfields = (char **) rolo_emalloc(n * sizeof(char *));
  2384.      new_entry -> other_fields = otherfields;
  2385.      for (j = 0; j < n; j++) {  
  2386.          set_other_field(j,new_entry,copystr(get_other_field(j,entry)));
  2387.      }
  2388.   }     
  2389.   else new_entry -> other_fields = 0;     
  2390.      
  2391.   return(new_entry);     
  2392.      
  2393. }
  2394.  
  2395.  
  2396. rolo_update_mode (rlink) Ptr_Rolo_List rlink;
  2397.  
  2398. /* Update the fields of an entry.  The user is not allowed to modify the */
  2399. /* timestamp field. */
  2400.  
  2401. {
  2402.   int rval,menuval,findex,updated,newlen,n,nfields,j,name_changed;
  2403.   char *response,*s,*newfield,*newval,*other, **others;
  2404.   Ptr_Rolo_Entry entry,old_entry;
  2405.         
  2406.   cancel_update :
  2407.   
  2408.   entry = copy_entry(old_entry = get_entry(rlink));
  2409.  
  2410.   updated = 0;
  2411.   name_changed = 0;
  2412.   
  2413.   redisplay :
  2414.   
  2415.   display_entry_for_update(updated ? entry : old_entry);
  2416.   nfields = (N_BASIC_FIELDS - 1) + get_n_others(entry);
  2417.   
  2418.   reask :  
  2419.   
  2420.   cathelpfile(libdir("updatemenu"),0,0);  
  2421.   
  2422.   rval = menu_match (
  2423.        &menuval,&response,
  2424.        ": ",
  2425.        0,1,0,1,4,
  2426.        "\\",U_ABORT,
  2427.        "?",U_HELP,
  2428.        "Help",U_HELP,
  2429.        "",U_END_UPDATE
  2430.     );
  2431.     
  2432.   switch (rval) {    
  2433.     
  2434.     case MENU_MATCH :
  2435.   
  2436.       switch (menuval) {
  2437.  
  2438.         case U_HELP :
  2439.           cathelpfile(libdir("updatehelp"),"updating",1);
  2440.           any_char_to_continue();
  2441.           clear_the_screen();
  2442.           goto redisplay;
  2443.  
  2444.         case U_ABORT :
  2445.           if (updated) {
  2446.              printf("Previous updates to fields in this entry ignored\n");
  2447.           }
  2448.           return;
  2449.           break;
  2450.  
  2451.         case U_END_UPDATE :
  2452.           if (!updated) goto reask;
  2453.           display_entry(entry);
  2454.           if (MENU_YES == rolo_menu_yes_no (
  2455.                    "Confirm Update? ",DEFAULT_YES,1,
  2456.                    "confirmhelp","confirming update"
  2457.                 )) {
  2458.              printf("Update confirmed\n");
  2459.              sleep(1);
  2460.              set_entry(rlink,entry);
  2461.              if (name_changed) {
  2462.                 rolo_delete(rlink);
  2463.                 rolo_insert(rlink,compare_links);
  2464.              }
  2465.              changed = 1;
  2466.              return;
  2467.           }
  2468.           else {   
  2469.              printf("Updates ignored...\n");
  2470.              sleep(1);
  2471.              updated = 0;
  2472.              goto cancel_update;
  2473.           }
  2474.          break;
  2475.        
  2476.       }
  2477.       break;
  2478.      
  2479.     case MENU_NO_MATCH : 
  2480.  
  2481.       /* check that the response is an integer within range */
  2482.  
  2483.       findex = str_to_pos_int(response,1,nfields+1);
  2484.       if (findex < 0) {
  2485.          printf("Not a valid number...Please try again\n");
  2486.          goto reask;
  2487.       }
  2488.       findex--;
  2489.  
  2490.       /* we can either be updating a standard field or a user-defined field */
  2491.       /* or adding a new field */
  2492.  
  2493.       if (findex < N_BASIC_FIELDS - 1) {
  2494.          name_changed = (findex == 0);
  2495.          printf("Updating '%s'\n",Field_Names[findex]);
  2496.          printf("Old value: %s\n",get_basic_rolo_field(findex,entry));
  2497.          printf("New value: ");
  2498.          if (0 == (newval = copystr(get_new_value()))) break;
  2499.          set_basic_rolo_field(findex,entry,newval);
  2500.          updated = 1;
  2501.       }
  2502.       else if (findex != nfields) {
  2503.          findex -= N_BASIC_FIELDS - 1;
  2504.          printf("Updating \'");
  2505.          s = other = get_other_field(findex,entry);
  2506.          while (*s != ':') putc(*s++,stdout);
  2507.          printf("\' field\n");
  2508.          printf("Old value: %s\n",++s);
  2509.          printf("New value: ");
  2510.          if (0 == (newval = copystr(get_new_value()))) break;
  2511.          if (strlen(newval) == 0) {
  2512.             for (j = findex; j < get_n_others(entry); j++) {
  2513.                 set_other_field(j,entry,get_other_field(j+1,entry));
  2514.             }
  2515.             set_n_others(entry,get_n_others(entry) - 1);
  2516.          }
  2517.          else {   
  2518.             *s = '\0';
  2519.             newlen = strlen(other) + strlen(newval) + 2;
  2520.             newfield = rolo_emalloc(newlen);
  2521.             nbuffconcat(newfield,3,other," ",newval);
  2522.             set_other_field(findex,entry,newfield);
  2523.          }
  2524.          updated = 1;
  2525.       }
  2526.       else {
  2527.         loop:
  2528.         printf("New field (<name>: <value>): ");
  2529.         if (0 == (newfield = copystr(get_new_value()))) break;
  2530.         if (0 == index(newfield,':')) {
  2531.            fprintf(stderr,"No field name.  Use a ':'...\n");
  2532.            goto loop;
  2533.         }
  2534.         n = get_n_others(entry);
  2535.         set_n_others(entry,n + 1);
  2536.         others = (char **) rolo_emalloc((n + 1) * sizeof(char *));
  2537.         for (j = 0; j < n; j++) others[j] = get_other_field(j,entry);
  2538.         others[n] = newfield;
  2539.         entry -> other_fields = others;
  2540.         updated = 1;
  2541.       }
  2542.       break;
  2543.  
  2544.     case MENU_EOF :
  2545.       user_eof();
  2546.       break;
  2547.       
  2548.     default :      
  2549.       fprintf(stderr,"Impossible return from update menu_match\n");
  2550.       save_and_exit(-1);
  2551.       break;
  2552.      
  2553.   }
  2554.  
  2555.   goto redisplay;
  2556.  
  2557. }
  2558. SHAR_EOF
  2559. if test 6022 -ne "`wc -c < 'update.c'`"
  2560. then
  2561.     echo shar: error transmitting "'update.c'" '(should have been 6022 characters)'
  2562. fi
  2563. fi
  2564. exit 0
  2565. #    End of shell archive
  2566.